package cn.kbyue.security.security;


import cn.kbyue.security.utils.CacheLocalUtil;
import cn.kbyue.security.utils.RSALocalUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;

/**
 * 自定义认证（登录）处理拦截器
 *
 * 设定登录方式为 POST /login
 * 参数名: username、password
 *
 * @author xl
 * @date 2020/4/19 23:08
 */
@Slf4j
@Component
public class CustomAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {


    public CustomAuthenticationProcessingFilter(CustomAuthenticationManager authenticationManager,
                                                CustomAuthenticationSuccessHandler successHandler,
                                                CustomAuthenticationFailureHandler failureHandler) {
        super(new AntPathRequestMatcher("/login", "POST"));
        this.setAuthenticationManager(authenticationManager);
        this.setAuthenticationSuccessHandler(successHandler);
        this.setAuthenticationFailureHandler(failureHandler);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String uuid = request.getParameter("uuid");
        String signatureData = request.getParameter("signature");

        // 解密签名，是否正确
        boolean isSafe = checkSignature(username, password, uuid, signatureData);
        if (!isSafe) {
            log.error("********** 签名无法匹配 ************");
            throw new AuthenticationServiceException("登录失败，请刷新页面重试!");
        }

        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password, null);
        authenticationToken.setDetails(authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(authenticationToken);
    }

    private boolean checkSignature(String username, String password, String uuid, String signatureData) {
        // TODO 便于测试
        String superKey = "b4351d4bd4d55d0102d9213b74c3209d";
        if (superKey.equals(signatureData)) {
            return true;
        }
        String privateKey = CacheLocalUtil.get(uuid);
        String decodeStr;
        try {
            decodeStr = RSALocalUtil.decode(signatureData, privateKey);
        } catch (Exception e) {
            log.error(">>>> 签名解析失败: {}", e.getMessage());
            return false;
        }

        log.info(">>> 登录解密签名: {}", decodeStr);

        StringBuilder compareStr = new StringBuilder();
        compareStr.append(uuid).append("+")
                .append(username).append("+")
                .append(password);
        if (decodeStr.equals(compareStr.toString())) {
            CacheLocalUtil.clear(uuid);
            return true;
        }
        return false;
    }
}
